package cmd

import (
	"encoding/json"
	"errors"
	"fmt"
	"go-ws-server/initData"
	rediscli "go-ws-server/redis"
	"go-ws-server/ws/manager"
	"log"
	"strings"
	"time"

	"go-ws-server/model/dto"

	"github.com/gorilla/websocket"
)

// Cmd 解析 [Main]
func HandleMessage(userId string, msg []byte, conn *websocket.Conn) {
	var req WsRequest

	//将 JSON 格式的字节数据 (msg []byte) 解析到目标结构体 (&req)
	if err := json.Unmarshal(msg, &req); err != nil {
		log.Println("消息解析失败:", err)
		return
	} else {
		log.Println("解析消息成功：", req)
	}

	switch req.Cmd {
	case "1001":
		HandleSendToUser(userId, req)
	case "1002":
		HandleSendToAll(userId, req)
	case "1003":
		QueryOnlineUser(userId)
	case "1004":
		QueryUserMessageList(userId, conn)
	case "1005":
		getMessageDetail(conn, req)
	case "1006":
		SendMessgaeHandle(conn, req, userId)
	default:
		log.Println("未知指令:", req.Cmd)
	}
}

/* 处理 发送消息给指定人 */
type WsRequest struct {
	Cmd     string            `json:"cmd"`
	To      string            `json:"to,omitempty"`
	Message string            `json:"message,omitempty"`
	Ext     map[string]string `json:"ext,omitempty"`
}

type WSResponse struct {
	Cmd     int         `json:"cmd"`     // 指令码，对应请求
	Code    int         `json:"code"`    // 0成功，非0失败
	Message string      `json:"message"` // 提示信息
	Data    interface{} `json:"data"`    // 返回数据
}

// 消息推送Req
type MessageReq struct {
	UserID      string `json:"userId"`
	AcceptID    string `json:"acceptId"`
	MessageType string `json:"messageType"`
	Content     string `json:"content"`
	Title       string `json:"title"`
}

// CMD: 1001; 发送给指定用户
func HandleSendToUser(userId string, msg WsRequest) error {
	log.Printf("处理10001指令 - 发送方: %s, 接收方: %s", userId, msg.To)

	// 校验目标用户
	if msg.To == "" {
		return errors.New("empty target user")
	}

	// 校验消息内容
	if strings.TrimSpace(msg.Message) == "" {
		return errors.New("message cannot be empty")
	}

	// 发送消息
	if err := manager.SendToUser(msg.To, msg.Message); err != nil {
		log.Printf("消息发送失败 - 发送方: %s, 接收方: %s, 错误: %v",
			userId, msg.To, err)
		return fmt.Errorf("send failed: %w", err)
	}

	return nil
}

// CMD: 1002; 发送消息给全部用户
func HandleSendToAll(userId string, msg WsRequest) {

	log.Println("调用：10002 指令；用户ID：", userId)

	log.Println("用户：", userId, "发送消息给全部用户：", msg.Message)

	manager.PushToAll(msg.Message, userId)
}

// CMD: 1003；查询在线用户信息
/**
{
    "CMD": "1003",
    "userId": "1934293164587802625",
}
*/
func QueryOnlineUser(userId string) {

	log.Println("调用：10003 指令；用户ID：", userId)

	log.Println("当前在线用户:", rediscli.Rdb.SMembers(rediscli.Ctx, "online:users").Val())

}

// CMD: 1004；根据用户ID查询用户消息列表信息
/**
{
    "CMD": "1004",
    "userId": "1934293164587802625",
}
*/
func QueryUserMessageList(userId string, conn *websocket.Conn) {

	log.Println("调用：10004 指令；用户ID：", userId)

	messages, err := rediscli.GetMessageListByUserID(rediscli.Ctx, rediscli.Rdb, userId)
	if err != nil {
		log.Printf("查询消息失败: %v\n", err)
		return
	}

	if err != nil {
		resp := WSResponse{
			Cmd:     500,
			Code:    1,
			Message: "查询失败：" + err.Error(),
			Data:    nil,
		}
		conn.WriteJSON(resp)
		return
	}

	// 正常返回
	resp := WSResponse{
		Cmd:     11004,
		Code:    200,
		Message: "查询成功",
		Data:    messages,
	}

	conn.WriteJSON(resp)
}

// CMD: 1005; 查询消息详情信息
/**
{
    "CMD": "1005",
    "ext":{
        "userId": "1934293164587802625",
        "messageId": "29"
    }
}
*/
func getMessageDetail(conn *websocket.Conn, message WsRequest) {

	messageId := message.Ext["messageId"]

	userId := message.Ext["userId"]

	log.Println("调用：10005 指令；用户ID：", messageId)

	messageInfo, err := rediscli.GetMessageDetail(rediscli.Ctx, rediscli.Rdb, messageId, userId)

	log.Println("查询消息成功:", messageInfo)

	if err != nil {
		resp := WSResponse{
			Cmd:     500,
			Code:    1,
			Message: "查询失败：" + err.Error(),
			Data:    nil,
		}
		conn.WriteJSON(resp)
		return
	}

	// 正常返回
	resp := WSResponse{
		Cmd:     11005,
		Code:    200,
		Message: "查询成功",
		Data:    messageInfo,
	}

	conn.WriteJSON(resp)
}

// CMD: 1006; 发送消息
func SendMessgaeHandle(conn *websocket.Conn, req WsRequest, userId string) {

	RequestBody := MessageReq{
		UserID:      req.Ext["userId"],
		AcceptID:    req.Ext["acceptId"],
		MessageType: req.Ext["messageType"],
		Content:     req.Ext["content"],
		Title:       req.Ext["title"],
	}

	log.Println("请求体：", RequestBody)

	log.Println("消息类型：", RequestBody.MessageType)

	switch RequestBody.MessageType {

	case "天气提醒":
		recordBatchAdd(RequestBody, "天气提醒")
	case "系统通知":
		recordBatchAdd(RequestBody, "系统通知")
	case "订阅提醒":
		recordBatchAdd(RequestBody, "订阅提醒")
	default:
		return
	}
}

// 做消息推送
func recordBatchAdd(req MessageReq, msgType string) {
	log.Println("做消息推送！")
	if req.AcceptID == "-1" {
		// 批量推送给好友
		friendList, _ := GetFriendList(req.UserID) // 查询数据库

		for _, friend := range friendList {

			log.Println("推送给好友: ", friend)
			recordAdd(req, msgType, friend)
		}
	} else {
		// 精准推送
		recordAdd(req, msgType, req.AcceptID)
	}
}

// 消息录入数据库
func recordAdd(req MessageReq, msgType, acceptId string) {

	message := dto.Message{
		Title:       msgType,     //标题
		Content:     req.Content, //消息体
		SendType:    msgType,     //消息类型
		SendTime:    time.Now(),  //发送时间
		CreatedTime: time.Now(),  //创建时间
	}

	if err := initData.DB.Create(&message).Error; err != nil {
		log.Printf("消息插入失败: %v", err)
		return
	} else {
		log.Println("消息插入成功")
		rediscli.WriteSingleMessageToRedis(message)
	}

	userMessage := dto.UserMessage{
		UserID:      req.UserID, //用户ID
		AcceptID:    acceptId,   //接受者ID
		MessageID:   message.ID, //消息ID
		ReadStatus:  0,          //是否已读
		Deleted:     0,          //是否删除
		ReceiveTime: time.Now(), //接收时间
	}

	if err := initData.DB.Create(&userMessage).Error; err != nil {
		log.Printf("用户消息插入失败: %v", err)
	} else {
		log.Println("用户消息插入成功")

		rediscli.WriteSingleUserMessageToRedis(userMessage)
	}

	manager.PushRefreshToClient(acceptId)

}

/* 请求好友列表Resp */
type FriendRelationship struct {
	FriendID string `gorm:"column:friend_id"`
}

// 根据用户ID 查询好友列表
func GetFriendList(userId string) ([]string, error) {

	var relationships []FriendRelationship

	err := initData.DB.Table("l_friend_relationship").
		Where("user_id = ?", userId).
		Find(&relationships).Error

	if err != nil {
		return nil, err
	}

	// 提取好友ID列表
	friendIDs := make([]string, 0, len(relationships))
	for _, r := range relationships {
		friendIDs = append(friendIDs, r.FriendID)
	}

	return friendIDs, nil
}
